home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
language
/
pcl_src.zoo
/
extensions.lsp
< prev
next >
Wrap
Lisp/Scheme
|
1992-07-09
|
23KB
|
497 lines
;;;-*-Mode:LISP; Package: PCL; Base:10; Syntax:Common-lisp; -*-
;;;
;;; *************************************************************************
;;;
;;; File: extensions.lisp.
;;;
;;; by Trent E. Lange, Effective Date 04-23-92
;;;
;;;
;;; This file contains a small set of useful extensions to PCL.
;;;
;;; Permission is granted to any individual or institution to use, copy,
;;; modify and distribute this document.
;;;
;;; Suggestions, bugs, criticism and questions to lange@cs.ucla.edu
;;; *************************************************************************
;;;
(in-package 'pcl)
(eval-when (compile load eval)
(defvar *extensions-exports*
'(set-standard-instance-access
set-funcallable-instance-access
funcallable-instance-slot-value
set-funcallable-instance-slot-value
funcallable-instance-slot-boundp
standard-instance-slot-value
set-standard-instance-slot-value
standard-instance-slot-boundp
structure-instance-slot-value
set-structure-instance-slot-value
structure-instance-slot-boundp
#+pcl-user-instances
user-instance-slot-value
#+pcl-user-instances
set-user-instance-slot-value
#+pcl-user-instances
user-instance-slot-boundp
with-optimized-slots
with-standard-instance-slots
method-needs-next-methods-p
map-all-classes
finalize-all-classes
updater
record-updater))
)
(defclass updater ()
((dependent :initarg :dependent :reader dependent)))
(defun record-updater (class dependee dependent &rest initargs)
(let ((updater
(apply #'make-instance class :dependent dependent initargs)))
(add-dependent dependee updater)
updater))
(defun finalize-all-classes (&optional (root-name 't))
"Makes sure that all classes are finalized. If Root-Name is supplied,
then finalizes Root-Name and all of its subclasses and their subclasses."
(map-all-classes #'(lambda (class)
(unless (class-finalized-p class)
(finalize-inheritance class)))
root-name))
;;;
;;;
;;;
(defmacro slot-value-from-index (instance wrapper slot-name slots index)
"Returns instance's slot-value given slot-name's index."
(once-only (index)
`(if ,index
(let ((val (%svref ,slots ,index)))
(if (eq val ',*slot-unbound*)
(slot-unbound (wrapper-class ,wrapper) ,instance ,slot-name)
val))
(if *safe-to-use-slot-value-wrapper-optimizations-p*
(get-class-slot-value-1 ,instance ,wrapper ,slot-name)
(accessor-slot-value ,instance ,slot-name)))))
(defmacro set-slot-value-from-index
(instance wrapper slot-name slots index new-value)
"Sets instance's slot-value to new-value given slot-name's index."
(once-only (index)
`(if ,index
(setf (%svref ,slots ,index) ,new-value)
(if *safe-to-use-set-slot-value-wrapper-optimizations-p*
(set-class-slot-value-1 ,instance ,wrapper ,slot-name ,new-value)
(setf (accessor-slot-value ,instance ,slot-name) ,new-value)))))
(defsetf slot-value-from-index set-slot-value-from-index)
(defmacro with-slots-slot-value-from-index
(instance wrapper slot-name slots index variable-instance)
"Returns instance's slot-value given slot-name's index."
(cond
((consp wrapper)
`(let ((wrapper ,wrapper))
(unless (eq (wrapper-state wrapper) 't)
(setf wrapper (wrapper-state-trap wrapper ,instance)))
(with-slots-slot-value-from-index
,instance wrapper ,slot-name ,slots ,index ,variable-instance)))
(variable-instance
`(let ((,instance ,variable-instance))
(with-slots-slot-value-from-index
,instance ,wrapper ,slot-name ,slots ,index NIL)))
(T `(slot-value-from-index ,instance ,wrapper ,slot-name ,slots ,index))))
(defmacro set-with-slots-slot-value-from-index
(instance wrapper slot-name slots index variable-instance new-value)
"Sets instance's slot-value to new-value given slot-name's index."
(cond
((consp wrapper)
`(let ((wrapper ,wrapper))
(unless (eq (wrapper-state wrapper) 't)
(setf wrapper (wrapper-state-trap wrapper ,instance)))
(set-with-slots-slot-value-from-index
,instance wrapper ,slot-name ,slots ,index ,variable-instance
,new-value)))
(variable-instance
`(let ((,instance ,variable-instance))
(set-with-slot-slots-value-from-index
,instance ,wrapper ,slot-name ,slots ,index NIL ,new-value)))
(T
`(setf (slot-value-from-index ,instance ,wrapper ,slot-name ,slots ,index)
,new-value))))
(defsetf with-slots-slot-value-from-index
set-with-slots-slot-value-from-index)
(defmacro with-slots-slot-value-from-wrapper-and-slots
(instance slot-name wrapper slots-layout slots variable-instance)
(cond
(variable-instance
`(let ((,instance ,variable-instance))
(with-slots-slot-value-from-wrapper-and-slots
,instance ,slot-name ,wrapper ,slots-layout ,slots NIL)))
((consp wrapper)
`(if *safe-to-use-slot-value-wrapper-optimizations-p*
(let ((wrapper ,wrapper))
(unless (eq (wrapper-state wrapper) 't)
(setf wrapper (wrapper-state-trap wrapper ,instance)))
(slot-value-from-wrapper-and-slots ,instance ,slot-name
wrapper ,slots-layout ,slots NIL))
(accessor-slot-value ,instance ,slot-name)))
(T
`(if *safe-to-use-slot-value-wrapper-optimizations-p*
(slot-value-from-wrapper-and-slots
,instance ,slot-name ,wrapper ,slots-layout ,slots NIL)
(accessor-slot-value ,instance ,slot-name)))))
(defmacro set-with-slots-slot-value-from-wrapper-and-slots
(instance slot-name wrapper slots-layout slots variable-instance new-value)
(cond
(variable-instance
`(let ((,instance ,variable-instance))
(set-with-slots-slot-value-from-wrapper-and-slots
,instance ,slot-name ,wrapper ,slots-layout ,slots NIL ,new-value)))
((consp wrapper)
`(if *safe-to-use-set-slot-value-wrapper-optimizations-p*
(let ((wrapper ,wrapper))
(unless (eq (wrapper-state wrapper) 't)
(setf wrapper (wrapper-state-trap wrapper ,instance)))
(setf (slot-value-from-wrapper-and-slots ,instance ,slot-name
wrapper ,slots-layout ,slots NIL)
,new-value))
(setf (accessor-slot-value ,instance ,slot-name) ,new-value)))
(T
`(if *safe-to-use-set-slot-value-wrapper-optimizations-p*
(setf (slot-value-from-wrapper-and-slots
,instance ,slot-name ,wrapper ,slots-layout ,slots NIL)
,new-value)
(setf (accessor-slot-value ,instance ,slot-name) ,new-value)))))
(defsetf with-slots-slot-value-from-wrapper-and-slots
set-with-slots-slot-value-from-wrapper-and-slots)
(defun tree-memq-p (item form)
(cond ((consp form)
(or (tree-memq-p item (car form))
(tree-memq-p item (cdr form))))
(T (eq item form))))
(defmacro with-optimized-slots (slot-entries instance-form &body body)
"Optimized version of With-Slots that is faster because it factors out
functions common to all slot accesses on the instance. It has two
extensions to With-Slots: (1) the second value of slot-entries are
evaluated as forms rather than considered to be hard slot-names, allowing
access of variable slot-names. (2) if a :variable-instance keyword is
the first part of the body, then the instance-form is treated as a variable
form, which is always expected to return an instance of the same class.
The value of the keyword must be an instance that is the same class as
instance-form will always return."
;; E.g. (with-optimized-slots (foo-slot
;;